#include "edit.h"
#include "../../gui_al.h"
#include <gtk/gtk.h>
#include "../../journal.h"
#include "../../io.h"
#include "../../simple.h"
#include "../../cryptography.h"
#include "../../gui_io.h"
#include "gui_io.h"
#include "undo.h"
#include "../../srch_pane.h"
#include "../../second.h"
#include "../../settings.h"
#include "../../menu.h"
#include "link_wzrd.h"
#include "../../tabs.h"
#include "gui_al.h"


GtkWidget *mnu_new_lnk;


char *_term = NULL;


int *elog_gui_io_res_list = NULL;
int elog_gui_io_res_list_len = 0;
int elog_gui_io_res_cur = -1;


int _tab_edit_ignore = 0;


int _tab_edit_changed = 0;

int _elog_tab_edit_run(void *p)
{
	elog_gui_al_lock();
	elog_edit_highlight_do();
	elog_gui_al_unlock();
	return 0;		//stop
}

int elog_tab_edit_srch()
{
	const char *term = gtk_entry_get_text(GTK_ENTRY(_menu_srch_entry));
	if (term) {
		if (strlen(term) > 0) {
			gtk_widget_show(_res_srch_window);
		} else {
			gtk_widget_hide(_res_srch_window);
			elog_gui_al_lock();
			edit_gui_al_clearTextMarks();
			elog_gui_al_unlock();
			return 0;
		}
	} else {
		gtk_widget_hide(_res_srch_window);
		elog_gui_al_lock();
		edit_gui_al_clearTextMarks();
		elog_gui_al_unlock();
		return 0;
	}

	elog_edit_highlight_term(term);

	elog_scnd_run(_elog_tab_edit_run, "edit_search");
	_tab_edit_changed = 0;
	return 0;
}

int elog_tab_edit_res(const char *name, int n)
{
	edit_gui_al_jump_to(elog_gui_io_res_list[n]);
	elog_gui_io_res_cur = n;
	return 0;
}


void elog_edit_highlight_term(const char *term)
{
	if (_term != NULL)
		free(_term);

	if (term == NULL) {
		_term = NULL;
		return;
	}
	_term = elog_sp_strReplace(term, " ", "+");
}

void elog_edit_highlight_do()
{
	if (_term == NULL)
		return;

	edit_gui_al_setVisible(0);	//invisible
	edit_gui_al_clearTextMarks();
	elog_srch_pane_clear();

	char *txt = edit_gui_al_text(NULL);
	if (strlen(txt) < 2) {
		edit_gui_al_setVisible(1);	//visible
		free(txt);
		return;
	}
	int *list = elog_srch_listResults(txt, _term);
	int c;
	for (c = 0; list[c] != -1; c += 2) {
		edit_gui_al_markText(txt, &(txt[list[c]]),
				     &(txt[list[c + 1]]));
		char *text =
		    malloc((sizeof *text) * (list[c + 1] - list[c] + 26));
		text[0] = '\0';
		strncpy(text, &(txt[list[c]]), list[c + 1] - list[c] + 25);
		text[25] = '\0';


		elog_srch_pane_add_item(text, c);
		list[c] = elog_gui_al_locToOffset(list[c], txt);
		list[c + 1] = elog_gui_al_locToOffset(list[c + 1], txt);
		free(text);
	}

	elog_gui_io_res_list_len = c;
	if (elog_gui_io_res_list)
		free(elog_gui_io_res_list);
	elog_gui_io_res_list = list;
	elog_gui_io_res_cur = 0;

	edit_gui_al_setVisible(1);	//visible
	free(txt);
}

void elog_edit_view_next_result()
{
	if (elog_gui_io_res_list) {
		elog_gui_io_res_cur += 2;
		if (elog_gui_io_res_cur >= elog_gui_io_res_list_len)
			elog_gui_io_res_cur -= 2;
		edit_gui_al_jump_to(elog_gui_io_res_list
				    [elog_gui_io_res_cur]);
	}
}
void elog_edit_view_prev_result()
{
	if (elog_gui_io_res_list) {
		elog_gui_io_res_cur -= 2;
		if (elog_gui_io_res_cur < 0)
			elog_gui_io_res_cur = 0;
		edit_gui_al_jump_to(elog_gui_io_res_list
				    [elog_gui_io_res_cur]);
	}
}

int elog_tab_edit_cut()
{
	GtkTextBuffer *buffer =
	    gtk_text_view_get_buffer(GTK_TEXT_VIEW(_mainTextView));
	GtkTextMark *beg, *end;
	beg = gtk_text_buffer_get_mark(buffer, "insert");
	end = gtk_text_buffer_get_mark(buffer, "selection_bound");
	GtkTextIter st, nd;
	gtk_text_buffer_get_iter_at_mark(buffer, &st, beg);
	gtk_text_buffer_get_iter_at_mark(buffer, &nd, end);
	int x, y;
	x = gtk_text_iter_get_offset(&st);
	y = gtk_text_iter_get_offset(&nd);
	if (x == y)
		return 1;
	if (y < x) {
		gtk_text_buffer_get_iter_at_mark(buffer, &st, end);
		gtk_text_buffer_get_iter_at_mark(buffer, &nd, beg);
		int tmp = y;
		y = x;
		x = tmp;
	}
	char *txt = edit_gui_al_text(NULL);
	char *sentence = gtk_text_buffer_get_text(buffer, &st, &nd, TRUE);

	gtk_clipboard_set_text(gtk_clipboard_get_for_display
			       (gdk_display_get_default(),
				GDK_SELECTION_CLIPBOARD),
			       (gchar *) sentence, strlen(sentence));
			       


	/* this will check for links */
	int removed = 0;
	int c = x;
	for (; c <= y; ++c) {
		struct elog_xml_link *lnk;
		if (elog_gui_io_checkRange(c, &lnk)) {
			int i = c;
			for (; i <= y; ++i) {
				struct dict *lnk_1;
				if (elog_gui_io_checkRange(i, &lnk_1) == 0)	//does this span the link?
				{
					//it passes the right side, how about the left?
					int l = c;
					for (; l >= x; --l) {
						struct dict *lnk_2;
						if (elog_gui_io_checkRange(l, &lnk_2) == 0) { //does this span the left side?	
							elog_gui_io_removeLink(i - 1);	//remove link
							edit_gui_io_addUndoActionPtr
								    (EDIT_GUI_IO_ACTION_UNLINK,
								     lnk, lnk->start);
							i = y + 1;	//break the loop
							c = i;
							removed = 1;
						}
					}
				}
			}
			if (!(removed))
				return 1;
		}
	}  

	edit_gui_io_addUndoActionPtr(EDIT_GUI_IO_ACTION_CUT, sentence, x);
	edit_gui_io_updateTags(x, -1 * elog_gui_al_strlen(sentence));
	gtk_text_buffer_delete_interactive(buffer, &st, &nd, TRUE);


	free(txt);
	return 0;
}

int elog_tab_edit_copy()
{
	GtkTextBuffer *buffer =
	    gtk_text_view_get_buffer(GTK_TEXT_VIEW(_mainTextView));
	GtkTextMark *beg, *end;
	beg = gtk_text_buffer_get_mark(buffer, "insert");
	end = gtk_text_buffer_get_mark(buffer, "selection_bound");
	GtkTextIter st, nd;
	gtk_text_buffer_get_iter_at_mark(buffer, &st, beg);
	gtk_text_buffer_get_iter_at_mark(buffer, &nd, end);
	unsigned int x, y;
	x = gtk_text_iter_get_offset(&st);
	y = gtk_text_iter_get_offset(&nd);
	if (x == y)
		return 1;
	if (y < x) {
		gtk_text_buffer_get_iter_at_mark(buffer, &st, end);
		gtk_text_buffer_get_iter_at_mark(buffer, &nd, beg);
		int tmp = y;
		y = x;
		x = tmp;
	}

	char *txt = edit_gui_al_text(NULL);
	char *sentence = gtk_text_buffer_get_text(buffer, &st, &nd, TRUE);

	gtk_clipboard_set_text(gtk_clipboard_get_for_display
			       (gdk_display_get_default(),
				GDK_SELECTION_CLIPBOARD),
			       (gchar *) sentence, strlen(sentence));

	free(txt);
	return 0;
}

int elog_tab_edit_paste()
{
	gchar *txt =
	    gtk_clipboard_wait_for_text(gtk_clipboard_get_for_display
					(gdk_display_get_default(),
					 GDK_SELECTION_CLIPBOARD));
	elog_tab_edit_cut();
	if (!txt)
		return 1;
	char *text = (char *) txt;
	if (text[0] == 'L' && text[1] == 'O' && text[2] == 'C' && text[3] == 'A' && text[4] == 'T' && text[5] == 'I' && text[6] == 'O' && text[7] == 'N' && text[8] == ':' && text[9] == '/' && text[10] == '/') {	//text starts with LOCATION://; open the file and print it in.
		char *path = &(text[11]);
		struct elog_xml_doc *file = elog_crypt_open_dry(path);

		if (file) {
			unsigned int len;
			unsigned char *dat =
			    elog_io_readRestofFile(file->handle, &len);
			if (elog_journ_current()->settings->encryption[0] == 'A')	//then decrypt
				decryptText(dat, len);
			elog_io_close(file->handle);
			free(text);
			text = elog_sp_toChar(dat, len);
			elog_xml_doc_free(file);
		} else
			return 1;
	}
	//this code currently does nothing about links.
	GtkTextBuffer *buffer =
	    gtk_text_view_get_buffer(GTK_TEXT_VIEW(_mainTextView));
	GtkTextMark *mark = gtk_text_buffer_get_mark(buffer, "insert");
	GtkTextIter iter;
	gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark);
	int offset = gtk_text_iter_get_offset(&iter);
	edit_gui_io_addUndoActionPtr(EDIT_GUI_IO_ACTION_PASTE, text,
				     offset);
	edit_gui_al_insertStr(offset, text);
	edit_gui_io_updateTags(offset, elog_gui_al_strlen(text));

	return 0;
}

int elog_tab_edit_delete()
{
	GtkTextBuffer *buffer =
	    gtk_text_view_get_buffer(GTK_TEXT_VIEW(_mainTextView));
	GtkTextMark *beg, *end;
	beg = gtk_text_buffer_get_mark(buffer, "insert");
	end = gtk_text_buffer_get_mark(buffer, "selection_bound");
	GtkTextIter st, nd;
	gtk_text_buffer_get_iter_at_mark(buffer, &st, beg);
	gtk_text_buffer_get_iter_at_mark(buffer, &nd, end);
	int x, y;
	x = gtk_text_iter_get_offset(&st);
	y = gtk_text_iter_get_offset(&nd);
	if (x == y)
		return 1;
	if (y < x) {
		gtk_text_buffer_get_iter_at_mark(buffer, &st, end);
		gtk_text_buffer_get_iter_at_mark(buffer, &nd, beg);
		int tmp = y;
		y = x;
		x = tmp;
	}
	char *txt = edit_gui_al_text(NULL);
	char *sentence = gtk_text_buffer_get_text(buffer, &st, &nd, TRUE);

    
	/* this will check for links */
	int removed = 0;
	int c = x;
	for (; c <= y; ++c) {
		struct elog_xml_link *lnk;
		if (elog_gui_io_checkRange(c, &lnk)) {
			int i = c;
			for (; i <= y; ++i) {
				struct elog_xml_link *lnk_1;
				if (elog_gui_io_checkRange(i, &lnk_1) == 0)	//does this span the link?
				{
					//it passes the right side, how about the left?
					int l = c;
					for (; l >= x; --l) {
						struct elog_xml_link *lnk_2;
						if (elog_gui_io_checkRange(l, &lnk_2) == 0) { //does this span the left side?	
							elog_gui_io_removeLink(i - 1);	//remove link
							edit_gui_io_addUndoActionPtr
								    (EDIT_GUI_IO_ACTION_UNLINK,
								     lnk, lnk->start);
							i = y + 1;	//break the loop
							c = i;
							removed = 1;
						}
					}
				}
			}
			if (!(removed))
				return 1;
		}
	}  

	edit_gui_io_addUndoActionPtr(EDIT_GUI_IO_ACTION_CUT, sentence, x);
	edit_gui_io_updateTags(x, -1 * elog_gui_al_strlen(sentence));
	gtk_text_buffer_delete_interactive(buffer, &st, &nd, TRUE);


	free(txt);
	return 0;
}

int _text_position = -1;
int _changed = 0;

//The following functions handles virtually all textBox events.
//First it handles mouse events, and then it deals with keyboard events.

gboolean    on_text_cursor_move_real                  (GtkWidget      *widget,
                                            GdkEventMotion *event,
                                            gpointer        user_data)
{
	printf("leave..\n");
	return TRUE;
	GtkAdjustment *adj =
		gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW
						(_mainScroll));
	int off_y = (int) gtk_adjustment_get_value(adj);

	GtkTextIter iter1;
	gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW
						(_textBox),
						&iter1,
						(int) (((GdkEventButton *)
							event)->
							x),
						(int) (((GdkEventButton *)
							event)->
							y) +
						off_y);
	int pos = gtk_text_iter_get_offset(&iter1);
	struct elog_xml_link *lnk;
	printf("%i\n", pos);
	if (elog_gui_io_checkRange(pos, &lnk)) {
		gdk_cursor_new_for_display(gdk_display_get_default(), GDK_HAND2);
	}
	else {
		gdk_cursor_new_for_display(gdk_display_get_default(), GDK_LEFT_PTR);
	}
	elog_gui_al_setLockMode(ELOG_GUI_AL_LOCKED);
	
	return TRUE;	
}


gboolean
on_text_cursor_move(GtkTextView * txt,
		    GdkEvent * event, gpointer user_data)
{
	if (_tab_edit_ignore)
		return FALSE;
	elog_gui_al_setLockMode(ELOG_GUI_AL_LOCK_CALLBACK);


	if (event->type == GDK_BUTTON_PRESS) {
		GtkAdjustment *adj =
		    gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW
							(_mainScroll));
		int off_y = (int) gtk_adjustment_get_value(adj);

		if (((GdkEventButton *) event)->button == 1) {
			GtkTextIter iter1;
			gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW
							   (_textBox),
							   &iter1,
							   (int) (((GdkEventButton *)
								   event)->
								  x),
							   (int) (((GdkEventButton *)
								   event)->
								  y) +
							   off_y);
			int pos = gtk_text_iter_get_offset(&iter1);
			struct elog_xml_link *lnk;
			if (elog_gui_io_checkRange(pos, &lnk)) {
				elog_gui_io_fileHandler(lnk->href);
				elog_gui_al_setLockMode(ELOG_GUI_AL_LOCKED);
				return TRUE;
			}
			elog_gui_al_setLockMode(ELOG_GUI_AL_LOCKED);
			return FALSE;
		}
		if (((GdkEventButton *) event)->button == 2) {
			GtkTextIter iter1;
			gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW
							   (_textBox),
							   &iter1,
							   (int) (((GdkEventButton *)
								   event)->
								  x),
							   (int) (((GdkEventButton *)
								   event)->
								  y +
								  off_y));
			_text_position = gtk_text_iter_get_offset(&iter1);
			elog_gui_al_setLockMode(ELOG_GUI_AL_LOCKED);
			return FALSE;
		}
		if (((GdkEventButton *) event)->button == 3) {
			GtkTextIter iter1;
			gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW
							   (_textBox),
							   &iter1,
							   (int) (((GdkEventButton *)
								   event)->
								  x),
							   (int) (((GdkEventButton *)
								   event)->
								  y) +
							   off_y);
			int pos = gtk_text_iter_get_offset(&iter1);
			struct elog_xml_link *lnk;
			if (elog_gui_io_checkRange(pos, &lnk)) {
				GtkTextTag *tag;
				GtkTextBuffer *buffer =
				    gtk_text_view_get_buffer(GTK_TEXT_VIEW
							     (_textBox));
				GtkTextTagTable *table =
				    gtk_text_buffer_get_tag_table(buffer);

				char *name =
				    elog_sp_shortToString(lnk->num);

				tag =
				    gtk_text_tag_table_lookup(table,
							      (gchar *)
							      name);

				view_popup_menu((GtkWidget *) tag,
						(GdkEventButton *) event,
						NULL);
				free(name);
				elog_gui_al_setLockMode(ELOG_GUI_AL_LOCKED);
				return TRUE;
			} else {
				GtkTextBuffer *buffer =
				    gtk_text_view_get_buffer(txt);
				GtkTextMark *sel1 =
				    gtk_text_buffer_get_mark
				    (GTK_TEXT_BUFFER(buffer),
				     "insert");
				GtkTextMark *sel2 =
				    gtk_text_buffer_get_mark
				    (GTK_TEXT_BUFFER(buffer),
				     "selection_bound");
				GtkTextIter iter1;
				GtkTextIter iter2;
				gtk_text_buffer_get_iter_at_mark
				    (GTK_TEXT_BUFFER(buffer), &iter1,
				     sel1);
				gtk_text_buffer_get_iter_at_mark
				    (GTK_TEXT_BUFFER(buffer), &iter2,
				     sel2);
				guint pos1, pos2;


				pos1 = gtk_text_iter_get_offset(&iter1);

				pos2 = gtk_text_iter_get_offset(&iter2);
				GtkWidget *new_lnk = mnu_new_lnk;

				gtk_widget_set_sensitive(new_lnk,
							 !(pos1 == pos2));

				GdkEventButton *button =
				    (GdkEventButton *) event;
				gtk_menu_popup(GTK_MENU(user_data), NULL,
					       NULL, NULL, NULL,
					       button->button,
					       button->time);
			}
			//else we need to pop up a copy/paste/etc menu.
			elog_gui_al_setLockMode(ELOG_GUI_AL_LOCKED);
			return TRUE;
		}
	}
	elog_gui_al_setLockMode(ELOG_GUI_AL_LOCKED);
	if (event->type != GDK_KEY_PRESS)
		return FALSE;


	_changed++;
	GtkTextBuffer *buffer = gtk_text_view_get_buffer(txt);
	GtkTextMark *sel1 =
	    gtk_text_buffer_get_mark(GTK_TEXT_BUFFER(buffer), "insert");
	GtkTextMark *sel2 =
	    gtk_text_buffer_get_mark(GTK_TEXT_BUFFER(buffer),
				     "selection_bound");
	GtkTextIter iter1;
	GtkTextIter iter2;
	gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(buffer), &iter1,
					 sel1);
	gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(buffer), &iter2,
					 sel2);
	guint pos1, pos2;


	pos1 = gtk_text_iter_get_offset(&iter1);

	pos2 = gtk_text_iter_get_offset(&iter2);

	if (pos1 > pos2 && pos2 != 0)	//flipping 
		//in case they select in different directions.
	{
		guint tmp = pos1;
		pos1 = pos2;
		pos2 = tmp;
	}

	int selected = 1;

	if (pos1 != pos2)
		selected = pos2 - pos1;

	guint key = ((GdkEventKey *) event)->keyval;
	guint meta = ((GdkEventKey *) event)->state;

	meta = meta & GDK_CONTROL_MASK;
	if (meta == GDK_CONTROL_MASK && key == GDK_z) {	//Begin Undo
		elog_gui_al_setLockMode(ELOG_GUI_AL_LOCK_CALLBACK);
		edit_gui_io_undo();
		elog_gui_al_setLockMode(ELOG_GUI_AL_LOCKED);
		return TRUE;
	}
	if (meta == GDK_CONTROL_MASK && key == GDK_y) {	//Begin redo
		elog_gui_al_setLockMode(ELOG_GUI_AL_LOCK_CALLBACK);
		edit_gui_io_redo();
		elog_gui_al_setLockMode(ELOG_GUI_AL_LOCKED);
		return TRUE;
	}

	struct elog_xml_link *lnk;
	int inlnk = elog_gui_io_checkRange(pos1, &lnk);


	guint delete = GDK_Delete;
	if (key == GDK_Up ||
	    key == GDK_Left || key == GDK_Right || key == GDK_Down) {

		//gtk_text_buffer_place_cursor(buffer, &iter2);
		return FALSE;
	}
	if (key == GDK_End || key == GDK_Home || key == GDK_Page_Up
	    || key == GDK_Page_Down) {
		return FALSE;
	}
	if (key == GDK_Return) {
		if (inlnk == 1) {
			elog_gui_al_setLockMode(ELOG_GUI_AL_LOCK_CALLBACK);
			elog_gui_io_fileHandler(lnk->href);
			elog_gui_al_setLockMode(ELOG_GUI_AL_LOCKED);
			return TRUE;
		}
	}
	if (key == GDK_BackSpace && inlnk == 0 && pos1 == pos2)	//single character
	{
		if (elog_gui_io_checkRange(pos1 - 1, &lnk))
			return TRUE;

		GtkTextIter beg;
		gtk_text_buffer_get_iter_at_offset(buffer, &beg, pos1 - 1);
		unsigned int x =
		    g_utf8_get_char(gtk_text_buffer_get_text
				    (buffer, &beg, &iter1, TRUE));

		edit_gui_io_addUndoAction(EDIT_GUI_IO_ACTION_DEL, x,
					  pos1 - 1);

		edit_gui_io_updateTags(pos1 - 1, -1 * selected);
		return FALSE;
	}
	if (key == delete && inlnk == 0 && pos1 == pos2)	//single character
	{
		GtkTextIter beg;
		gtk_text_buffer_get_iter_at_offset(buffer, &beg, pos2 + 1);
		unsigned int x =
		    g_utf8_get_char(gtk_text_buffer_get_text
				    (buffer, &beg, &iter1, TRUE));
		edit_gui_io_addUndoAction(EDIT_GUI_IO_ACTION_DEL, x, pos1);
		edit_gui_io_updateTags(pos1, -1 * selected);
		return FALSE;
	}

	if ((key == GDK_BackSpace || key == delete) && inlnk == 0)	//multi-character
	{
		/*if (selected == 1)
		   gtk_text_buffer_backspace(buffer, &iter1, TRUE, TRUE);
		   else
		   gtk_text_buffer_delete_interactive(buffer, &iter1, &iter2, TRUE); */

		GtkTextIter beg;
		gtk_text_buffer_get_iter_at_offset(buffer, &beg, pos1 - 1);
		char *x =
		    gtk_text_buffer_get_text(buffer, &iter1, &iter2, TRUE);

		int c = pos1;
		for (; c <= pos2; ++c) {
			struct elog_xml_link *lnk;
			if (elog_gui_io_checkRange(c, &lnk)) {
				int removed = 0;
				int i = c;
				for (; i <= pos2; ++i) {
					struct elog_xml_link *lnk_1;
					if (elog_gui_io_checkRange(i, &lnk_1) == 0)	//does this span the link?
					{
						//it passes the right side, how about the left?
						int l = c;
						for (; l >= pos1; --l) {
							struct elog_xml_link *lnk_2;
							if (elog_gui_io_checkRange(l, &lnk_2) == 0) { //does this span the left side?	
								elog_gui_io_removeLink(i - 1);	//remove link
								edit_gui_io_addUndoActionPtr
									    (EDIT_GUI_IO_ACTION_UNLINK,
									     lnk, lnk->start);
								i = pos2 + 1;	//break the loop
								c = i;
								removed = 1;		
							}
						}
					}
				}
				if (!(removed))
					return TRUE;
			}
		}
		edit_gui_io_addUndoActionPtr(EDIT_GUI_IO_ACTION_CUT, x,
					     pos1);
		edit_gui_io_updateTags(pos1, -1 * selected);
		return FALSE;
	}


	if (inlnk == 1)
		return TRUE;



	if (key == GDK_Tab) {
		edit_gui_io_updateTags(pos1, selected);
		edit_gui_io_addUndoAction(EDIT_GUI_IO_ACTION_CHAR, GDK_Tab,
					  pos1);
		return FALSE;
	}
	if (pos1 != pos2 && pos2 != 0) {
		if (strlen(((GdkEventKey *)(event))->string) > 0) {
		 	edit_gui_io_updateTags(pos1, ((pos1 - pos2)));
		 	char *cut = edit_gui_al_getSelectedText();
	   		edit_gui_io_addUndoActionPtr(EDIT_GUI_IO_ACTION_CUT, cut, pos1);
		}
	}

	elog_gui_al_setLockMode(ELOG_GUI_AL_LOCK_CALLBACK);

	if (key == GDK_Return || key == GDK_period || key == GDK_question
	    || key == GDK_colon || key == GDK_parenright
	    || key == GDK_exclam)
		if (_changed > 10) {
			_changed = 0;
			elog_gui_io_save();
			elog_tab_edit_srch();
			_tab_edit_changed = 1;
		}

	if (_changed > 50) {
		_changed = 0;
		elog_gui_io_save();
		_tab_edit_changed = 1;
	}

	elog_gui_al_setLockMode(ELOG_GUI_AL_LOCKED);
	return FALSE;
}

void on_link_btn_activate(GtkButton * button, gpointer user_data)
{
	elog_gui_io_save();

	GtkTextBuffer *buffer =
	    gtk_text_view_get_buffer(GTK_TEXT_VIEW(_textBox));
	GtkTextMark *sel1 =
	    gtk_text_buffer_get_mark(GTK_TEXT_BUFFER(buffer), "insert");
	GtkTextMark *sel2 =
	    gtk_text_buffer_get_mark(GTK_TEXT_BUFFER(buffer),
				     "selection_bound");
	GtkTextIter iter1;
	GtkTextIter iter2;
	gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(buffer), &iter1,
					 sel1);
	gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(buffer), &iter2,
					 sel2);
	guint pos1, pos2;


	pos1 = gtk_text_iter_get_offset(&iter1);


	pos2 = gtk_text_iter_get_offset(&iter2);



	if (pos2 > pos1) {
		guint pos3 = pos1;
		pos1 = pos2;
		pos2 = pos3;
	}

	if (pos1 != pos2) {
		int *locs = malloc((sizeof *locs) * 2);
		locs[0] = pos1;
		locs[1] = pos2;
		GtkWidget *link = create_link_window(locs);
		gtk_widget_show_all(link);
		gtk_main();
		free(locs);
	}

}
void on_attch_btn_activate(GtkButton * button, gpointer user_data)
{
	elog_gui_io_save();

	GtkTextBuffer *buffer =
	    gtk_text_view_get_buffer(GTK_TEXT_VIEW(_textBox));
	GtkTextMark *sel1 =
	    gtk_text_buffer_get_mark(GTK_TEXT_BUFFER(buffer), "insert");
	GtkTextMark *sel2 =
	    gtk_text_buffer_get_mark(GTK_TEXT_BUFFER(buffer),
				     "selection_bound");
	GtkTextIter iter1;
	GtkTextIter iter2;
	gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(buffer), &iter1,
					 sel1);
	gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(buffer), &iter2,
					 sel2);
	guint pos1, pos2;


	pos1 = gtk_text_iter_get_offset(&iter1);


	pos2 = gtk_text_iter_get_offset(&iter2);



	if (pos2 != pos1) {
		elog_wrn_print("Unselect your text first.\n");
		return;
	}
	//To be written, logic/ui for attaching stuff!
	elog_wrn_print("Sorry, this feature isn't implemented yet.  Stay tuned!");
}
void on_buffer_insert(GtkTextBuffer * textbuffer,
		      GtkTextIter * arg1,
		      gchar * arg2, gint arg3, gpointer user_data)
{
	if (_tab_edit_ignore)
		return;

	
	if (_text_position >= 0) {
		edit_gui_io_updateTags(_text_position, arg3);
		char *str;
		elog_sp_cat(&str, (char *) arg2, NULL);	//undo frees its own, must put in copy.
		edit_gui_io_addUndoActionPtr(EDIT_GUI_IO_ACTION_PASTE, str,
					     _text_position);
		_text_position = -1;
	} else {
		if (g_utf8_strlen(arg2, -1) == 1) {
			GtkTextBuffer *buffer = textbuffer;
			GtkTextMark *sel1 =
			    gtk_text_buffer_get_mark(GTK_TEXT_BUFFER
						     (buffer),
						     "insert");
			GtkTextMark *sel2 =
			    gtk_text_buffer_get_mark(GTK_TEXT_BUFFER
						     (buffer),
						     "selection_bound");
			GtkTextIter iter1;
			GtkTextIter iter2;
			gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER
							 (buffer), &iter1,
							 sel1);
			gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER
							 (buffer), &iter2,
							 sel2);
			guint pos1, pos2;


			pos1 = gtk_text_iter_get_offset(&iter1);

			pos2 = gtk_text_iter_get_offset(&iter2);

			if (pos1 > pos2 && pos2 != 0)	//flipping 
				//in case they select in different directions.
			{
				guint tmp = pos1;
				pos1 = pos2;
				pos2 = tmp;
			}
			if (pos1 == pos2) {
				struct elog_xml_link *lnk;
				if (elog_gui_io_checkRange(pos1, &lnk))
					return;	//in a link.

				edit_gui_io_updateTags(pos1, 1);
				unsigned int val = g_utf8_get_char(arg2);

				edit_gui_io_addUndoAction(EDIT_GUI_IO_ACTION_CHAR,
						  val, pos1);
			} 

			
		}
	}
}
void on_mood_changed(GtkComboBox * widget, gpointer user_data)
{

	if (elog_gui_io_lock())
		return;
	if (edit_gui_al_weather(-1) >= 0)
		edit_gui_al_setImage(edit_gui_al_mood(-1),
				     edit_gui_al_weather(-1));

}

void on_weather_changed(GtkComboBox * widget, gpointer user_data)
{

	if (elog_gui_io_lock())
		return;
	if (edit_gui_al_mood(-1) >= 0)
		edit_gui_al_setImage(edit_gui_al_mood(-1),
				     edit_gui_al_weather(-1));

}
void
view_popup_menu(GtkWidget * txt, GdkEventButton * event, gpointer userdata)
{
	GtkWidget *menu, *menuitem;
	menu = gtk_menu_new();

	menuitem = gtk_menu_item_new_with_label("Remove Link");

	g_signal_connect(menuitem, "activate",
			 (GCallback) on_link_remove_activate, txt);

	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);

	gtk_widget_show_all(menu);

	/* Note: event can be NULL here when called from view_onPopupMenu;
	 *  gdk_event_get_time() accepts a NULL argument */
	gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
		       (event != NULL) ? event->button : 0,
		       gdk_event_get_time((GdkEvent *) event));
}

void on_link_remove_activate(GtkButton * button, gpointer user_data)
{
	char *name;
	g_object_get(user_data, "name", (gchar **) & name, NULL);
	struct elog_xml_doc *doc;
	elog_set_currentFile(NULL, &doc);	//gets current document
	const struct elog_xml_link *lnk = elog_xml_lnk_find(doc, name);
	if (lnk == NULL)
		return;
	//getting integer location
	int loc = lnk->start - 1;

	elog_gui_io_removeLink(loc);
	edit_gui_io_addUndoActionPtr(EDIT_GUI_IO_ACTION_UNLINK,
				     (void *) lnk, loc);
}

void on_text_insert(GtkTextBuffer * textbuffer,
		    GtkTextIter * arg1,
		    gchar * arg2, gint arg3, gpointer user_data)
{
	printf("%s\n", arg2);

}
gboolean on_edit_pane_set(GtkWidget * widget,
			  GdkEventButton * event, gpointer user_data)
{
	elog_set_set_int("tree_divider", elog_gui_al_pane(-1));

	edit_gui_al_setImage(edit_gui_al_mood(-1),
			     edit_gui_al_weather(-1));

	return FALSE;
}
void elog_tab_edit_ignore_signals(int t)
{
	_tab_edit_ignore = t;
}

GtkWidget *elog_edit_initialize(GtkAccelGroup *accel_group)
{
	printf("Making the edit tab...\n");
	GtkWidget *vbox5;
	GtkWidget *vpaned1;
	GtkWidget *hbox3;
	GtkWidget *weather_cmbo;
	GtkWidget *mood_cmbo;
	GtkWidget *hbox1;
	GtkWidget *scrolledwindow3;
	GtkWidget *hpaned1;
	GtkWidget *vbox4;
	GtkWidget *subject_txt;
	GtkWidget *date_crt_lbl;
	GtkWidget *last_edt_txt;
	GtkWidget *link_txt;

	hpaned1 = gtk_hpaned_new();
	gtk_paned_set_position(GTK_PANED(hpaned1),
			       elog_set_get_int("tree_divider"));

	vbox4 = gtk_vbox_new(FALSE, 0);
	gtk_paned_pack1(GTK_PANED(hpaned1), vbox4, FALSE, TRUE);

	subject_txt = gtk_entry_new();
	gtk_box_pack_start(GTK_BOX(vbox4), subject_txt, FALSE, FALSE, 0);

	date_crt_lbl = gtk_label_new(_("Date Created"));

	gtk_label_set_use_markup(GTK_LABEL(date_crt_lbl), TRUE);


	last_edt_txt = gtk_label_new(_("Last Edit"));
	gtk_box_pack_start(GTK_BOX(vbox4), last_edt_txt, FALSE, FALSE, 0);

	link_txt = gtk_label_new(_(""));
	gtk_box_pack_start(GTK_BOX(vbox4), link_txt, FALSE, FALSE, 0);

	_sideImage = gtk_image_new();
	gtk_box_pack_start(GTK_BOX(vbox4), _sideImage, FALSE, FALSE, 0);

	vbox5 = gtk_vbox_new(FALSE, 0);

	


	vpaned1 = gtk_vbox_new(FALSE, 2);
	gtk_box_pack_start(GTK_BOX(vbox5), vpaned1, TRUE, TRUE, 0);


	
	hbox3 = gtk_hbox_new(FALSE, 0);

	gtk_box_pack_start(GTK_BOX(vpaned1), hbox3, FALSE, TRUE, 0);


	gtk_box_pack_start(GTK_BOX(hbox3), date_crt_lbl, FALSE, FALSE, 0);

	GtkWidget *label23 = gtk_label_new("  ");
	gtk_box_pack_start(GTK_BOX(hbox3), label23, FALSE, FALSE, 0);


	weather_cmbo = gtk_combo_box_new_text();
	gtk_box_pack_start(GTK_BOX(hbox3), weather_cmbo, TRUE, TRUE, 0);

	int c;
	char *name;
	for (c = 0; (name = elog_img_name_weather(c)) != NULL; ++c)
		gtk_combo_box_append_text(GTK_COMBO_BOX(weather_cmbo),
					  name);


	mood_cmbo = gtk_combo_box_new_text();
	gtk_box_pack_start(GTK_BOX(hbox3), mood_cmbo, TRUE, TRUE, 0);


	for (c = 0; (name = elog_img_name_smiley(c)) != NULL; ++c)
		gtk_combo_box_append_text(GTK_COMBO_BOX(mood_cmbo), name);


	hbox1 = gtk_hbox_new(FALSE, 0);
	gtk_paned_pack2(GTK_PANED(hpaned1), hbox1, TRUE, TRUE);



	scrolledwindow3 = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW
				       (scrolledwindow3),
				       GTK_POLICY_AUTOMATIC,
				       GTK_POLICY_AUTOMATIC);

	gtk_box_pack_start(GTK_BOX(hbox1), scrolledwindow3, TRUE, TRUE, 0);

	gtk_box_pack_end(GTK_BOX(vpaned1), hpaned1, TRUE, TRUE, 0);

	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW
					    (scrolledwindow3),
					    GTK_SHADOW_IN);


	/*defining main text right click menu */
	GtkWidget *txt_mnu = gtk_menu_new();
	GtkWidget *mnu_cut =
	    gtk_image_menu_item_new_from_stock("gtk-cut", accel_group);
	gtk_menu_insert(GTK_MENU(txt_mnu), mnu_cut, 0);
	gtk_widget_show(mnu_cut);


	GtkWidget *mnu_copy =
	    gtk_image_menu_item_new_from_stock("gtk-copy", accel_group);
	gtk_menu_insert(GTK_MENU(txt_mnu), mnu_copy, 1);
	gtk_widget_show(mnu_copy);

	GtkWidget *mnu_paste =
	    gtk_image_menu_item_new_from_stock("gtk-paste", accel_group);
	gtk_menu_insert(GTK_MENU(txt_mnu), mnu_paste, 2);
	gtk_widget_show(mnu_paste);

	GtkWidget *mnu_sep = gtk_separator_menu_item_new();
	gtk_menu_insert(GTK_MENU(txt_mnu), mnu_sep, 3);
	gtk_widget_show(mnu_sep);

	GtkWidget *mnu_new_lnk =
	    gtk_menu_item_new_with_label("Create New Link");
	gtk_menu_insert(GTK_MENU(txt_mnu), mnu_new_lnk, 4);
	gtk_widget_show(mnu_new_lnk);

	GtkWidget *mnu_new_atch =
	    gtk_menu_item_new_with_label("Attach File Here");
	gtk_menu_insert(GTK_MENU(txt_mnu), mnu_new_atch, 5);
	gtk_widget_show(mnu_new_atch);


	_mainTextView = gtk_text_view_new();
	gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(_mainTextView),
				    GTK_WRAP_WORD_CHAR);
	gtk_container_add(GTK_CONTAINER(scrolledwindow3), _mainTextView);


	g_signal_connect((gpointer) mnu_cut, "activate",
			 G_CALLBACK(on_cut1_activate), NULL);
	g_signal_connect((gpointer) mnu_copy, "activate",
			 G_CALLBACK(on_copy1_activate), NULL);
	g_signal_connect((gpointer) mnu_paste, "activate",
			 G_CALLBACK(on_paste1_activate), NULL);
	g_signal_connect((gpointer) mnu_new_lnk, "activate",
			 G_CALLBACK(on_link_btn_activate), NULL);
	g_signal_connect((gpointer) mnu_new_atch, "activate",
			 G_CALLBACK(on_attch_btn_activate), NULL);



	g_signal_connect((gpointer) mood_cmbo, "changed",
			 G_CALLBACK(on_mood_changed), NULL);
	g_signal_connect((gpointer) weather_cmbo, "changed",
			 G_CALLBACK(on_weather_changed), NULL);
	g_signal_connect((gpointer) _mainTextView, "event",
			 G_CALLBACK(on_text_cursor_move), txt_mnu);
	g_signal_connect((gpointer) _mainTextView, "leave-notify-event",
			 G_CALLBACK(on_text_cursor_move_real), txt_mnu);
	g_signal_connect((gpointer) hpaned1, "button_release_event",
			 G_CALLBACK(on_edit_pane_set), NULL);

	_date = last_edt_txt;
	_creationDate = date_crt_lbl;
	_links = link_txt;
	_textBox = _mainTextView;
	_mood = mood_cmbo;
	_weather = weather_cmbo;
	_subject = subject_txt;
	_mainHPane = hpaned1;
	_mainScroll = scrolledwindow3;


	return vbox5;
}	

void on_cut1_activate(GtkMenuItem * menuitem, gpointer user_data)
{
	elog_gui_al_setLockMode(ELOG_GUI_AL_LOCK_CALLBACK);
	elog_tab_act_cut();
	elog_gui_al_setLockMode(ELOG_GUI_AL_LOCKED);
}


void on_copy1_activate(GtkMenuItem * menuitem, gpointer user_data)
{
	elog_gui_al_setLockMode(ELOG_GUI_AL_LOCK_CALLBACK);
	elog_tab_act_copy();
	elog_gui_al_setLockMode(ELOG_GUI_AL_LOCKED);
}


void on_paste1_activate(GtkMenuItem * menuitem, gpointer user_data)
{
	elog_gui_al_setLockMode(ELOG_GUI_AL_LOCK_CALLBACK);
	elog_tab_act_paste();
	elog_gui_al_setLockMode(ELOG_GUI_AL_LOCKED);
}



gboolean on_text_tag_click(GtkTextTag * texttag,
			   GObject * arg1,
			   GdkEvent * event,
			   GtkTextIter * arg2, gpointer user_data)
{

	if (event->type == GDK_BUTTON_PRESS) {
		if (((GdkEventButton *) event)->button == 1) {
			char *name;
			g_object_get((gpointer *) texttag, "name",
				     (gchar **) & name, NULL);
			struct elog_xml_doc *doc;
			elog_set_currentFile(NULL, &doc);	//gets current document
			const struct elog_xml_link *lnk =
			    elog_xml_lnk_find(doc, name);
			if (lnk == NULL)
				return FALSE;

			elog_gui_io_fileHandler(lnk->href);

			return TRUE;
		}
		if (((GdkEventButton *) event)->button == 3) {
			view_popup_menu((GtkWidget *) texttag,
					(GdkEventButton *) event,
					user_data);
			return TRUE;
		} else
			return TRUE;
	}
	return FALSE;
}

